# -*- coding: utf-8 -*-
"""
Created on Tue May 14 11:31:28 2019

@author: solydo
"""
import TrainTree as tt
from DrawTree import draw
import numpy as np

#==============================================================
#                      表4.3 西瓜数据集3.0
#==============================================================
FeatureName=['色泽','根蒂','敲声','纹理','脐部','触感','密度','含糖率']
LabelName={1:'好瓜',0:'坏瓜'}
X=[['青绿','蜷缩','浊响','清晰','凹陷','硬滑',0.697,0.460],
   ['乌黑','蜷缩','沉闷','清晰','凹陷','硬滑',0.774,0.376],
   ['乌黑','蜷缩','浊响','清晰','凹陷','硬滑',0.634,0.264],
   ['青绿','蜷缩','沉闷','清晰','凹陷','硬滑',0.608,0.318],
   ['浅白','蜷缩','浊响','清晰','凹陷','硬滑',0.556,0.215],
   ['青绿','稍蜷','浊响','清晰','稍凹','软粘',0.403,0.237],
   ['乌黑','稍蜷','浊响','稍糊','稍凹','软粘',0.481,0.149],
   ['乌黑','稍蜷','浊响','清晰','稍凹','硬滑',0.437,0.211],
   ['乌黑','稍蜷','沉闷','稍糊','稍凹','硬滑',0.666,0.091],
   ['青绿','硬挺','清脆','清晰','平坦','软粘',0.243,0.267],
   ['浅白','硬挺','清脆','模糊','平坦','硬滑',0.245,0.057],
   ['浅白','蜷缩','浊响','模糊','平坦','软粘',0.343,0.099],
   ['青绿','稍蜷','浊响','稍糊','凹陷','硬滑',0.639,0.161],
   ['浅白','稍蜷','沉闷','稍糊','凹陷','硬滑',0.657,0.198],
   ['乌黑','稍蜷','浊响','清晰','稍凹','软粘',0.360,0.370],
   ['浅白','蜷缩','浊响','模糊','平坦','硬滑',0.593,0.042],
   ['青绿','蜷缩','沉闷','稍糊','稍凹','硬滑',0.719,0.103]]
Y=[1]*8+[0]*9

#==============================================================
#                比较基尼系数和信息熵两种划分方式
#==============================================================
#>>>>>>>>>在数据集3.0上的表现
tree=tt.CreatTree(X,Y,[],[],FeatureName,LabelName,rule='Gini')
draw(tree,'西瓜数据集3.0训练结果(基尼系数)')
tree=tt.CreatTree(X,Y,[],[],FeatureName,LabelName,rule='InfoGain')
draw(tree,'西瓜数据集3.0训练结果(信息熵)')
#>>>>>>>>>在数据集2.0上的表现
X_2_0=[x[:6] for x in X]  #数据集2.0
FeatureName_2_0=FeatureName[:6]
tree=tt.CreatTree(X_2_0,Y,[],[],FeatureName_2_0,LabelName,rule='Gini')
draw(tree,'西瓜数据集2.0训练结果(基尼系数)')
tree=tt.CreatTree(X_2_0,Y,[],[],FeatureName_2_0,LabelName,rule='InfoGain')
draw(tree,'西瓜数据集2.0训练结果(信息熵)')
#...结果显示无差别

#==============================================================
#                       划分测试集和验证集
#==============================================================
#>>>>>>>>>按表4.2方式划分测试集和验证集
X=[x[:6] for x in X]    #将数据集3.0转变为数据集2.0
FeatureName=FeatureName[:6]
trainindex=[0,1,2,5,6,9,13,14,15,16]
verifyindex=[3,4,7,8,10,11,12]
Xtrain=[X[i] for i in trainindex]
Xverify=[X[i] for i in verifyindex]
Ytrain=[Y[i] for i in trainindex]
Yverify=[Y[i] for i in verifyindex]

#==============================================================
#                  比较未剪枝，预剪枝，后剪枝
#==============================================================
#>>>>>>>>>未剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini')
draw(tree,'基于表4.2生成的未剪枝决策树')
#>>>>>>>>>预剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini',cut='pre',equalcut=True)
draw(tree,'基于表4.2生成的预剪枝决策树')
#>>>>>>>>>后剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini',cut='after',equalcut=False)
draw(tree,'基于表4.2生成的后剪枝决策树')
#...训练得到的决策树的根结点为“色泽”，而书本上为“脐部”，观察发现，
#...根结点在选择划分属性时，对于“色泽”和“脐部”，计算到的基尼系数相等，
#...按理说可以任意选择，为了与书本上符合，下面增加多个属性可选时的手动选择功能。

#==============================================================
#                        重复书本结果
#==============================================================
#>>>>>>>>>未剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini',equalchoose=True)
draw(tree,'基于表4.2生成的未剪枝决策树(手动选脐部)')
#>>>>>>>>>预剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini',cut='pre',equalcut=True,equalchoose=True)
draw(tree,'基于表4.2生成的预剪枝决策树(手动选脐部)')
#>>>>>>>>>后剪枝训练结果
tree=tt.CreatTree(Xtrain,Ytrain,Xverify,Yverify,FeatureName,LabelName,rule='Gini',cut='after',equalcut=False,equalchoose=True)
draw(tree,'基于表4.2生成的后剪枝决策树(手动选脐部)')
#...增加参数“equalchoose=True”，当遇到多个属性可以选择时，提示手动选择，
#...为了重复书本结果，根结点时需要选择“脐部”，其余结点，选择最前面的属性即可。
#...另外，注意到其中参数“equalcut”，该参数用于控制当剪枝前后精度相等时，是否剪枝，
#...按书本上做法，预剪枝时，若划分前后精度不变，则不划分，也就是要剪枝，因此，equalcut设为True
#...后剪枝时，若划分前后精度不变，则保留，也就是不剪枝，因此设equalcut为False。
#...但是，可以实验，对于预剪枝和后剪枝，equelcut均设为True或者False，得到结果完全一样。